"use strict";

/**唤醒当前网络的所有主机
 * @deprecated
 * */
async function wakeUpCurrentNetworkALLHost() {
    let toolsInstance = this;
    let tempTools = toolsInstance.lightCopy(toolsInstance);
    for (let hostCount = 0; hostCount < 10000; hostCount++) {
        tempTools.wakeUpCurrentNetworkPointHost(tempTools.randomMacGenerator()).then(val => console.log(val)).catch(val => console.log(val));
    }
}

/**唤醒当前网络指定的主机
 * @param macAddress : string 需要唤醒的MAC地址
 * @param {{
 *     interval_time:number,
 *     execute_count:number,
 *     broadcast_address:string,
 *     target_port:number
 * }} ConfigOption 参数对象
 * 以下是参数对象的属性
 * interval_time: 每次执行唤醒间隔时间,
 * execute_count: 需要执行唤醒次数,
 * broadcast_address: 唤醒广播地址,
 * target_port: 目标接收广播端口号
 * */
async function wakeUpCurrentNetworkPointHost(macAddress, ConfigOption) {
    let dgram_component = require('dgram');
    let network_component = require('net');
    function macAddressDetect(macData) {
        let FinalDetectValue;
        let splitSym = "~!@#$%^&*()-=[]{}\\|:;'\"/?,.<>`+_";
        try {
            switch (Object.prototype.toString.call(macData)) {
                case "[object String]":
                    let splitSymRec = [];
                    let rec1 = 0;
                    let rec2 = [];
                    let rec3;
                    for (let x1 = 0; x1 < String(splitSym).length; x1++) {
                        let tes = String(splitSym).charAt(x1);
                        splitSymRec[x1] = [tes];
                        for (let x2 = 0; x2 < String(macData).length; x2++) {
                            if (String(macData).charAt(x2) === tes) {
                                if (splitSymRec[x1].length > 1) {
                                    let nums = parseInt(splitSymRec[x1][1]);
                                    nums++;
                                    splitSymRec[x1][1] = nums;
                                } else {
                                    splitSymRec[x1].push(1);
                                }
                            }
                        }
                    }
                    for (let det in splitSymRec) {
                        if (splitSymRec[det].length > 1) {
                            rec1++;
                            rec2.push(splitSymRec[det]);
                        }
                    }
                    if (rec1 > 1) {
                        throw new Error("");
                    } else {
                        rec3 = String(macData).split(String(rec2[0][0]).toString());
                        if (rec3.length > 6) {
                            throw new Error("");
                        } else {
                            for (let x4 in rec3) {
                                for (let x3 = 0; x3 < String(rec3[x4]).length; x3++) {
                                    if (x3 > 1) {
                                        throw new Error("")
                                    } else {
                                        if (!Boolean(String(rec3[x4]).charCodeAt(x3) >= 48 && String(rec3[x4]).charCodeAt(x3) <= 57).valueOf() && !Boolean(String(rec3[x4]).charCodeAt(x3) >= 65 && String(rec3[x4]).charCodeAt(x3) <= 70).valueOf() && !Boolean(String(rec3[x4]).charCodeAt(x3) >= 97 && String(rec3[x4]).charCodeAt(x3) <= 102).valueOf()) {
                                            throw new Error("");
                                        }
                                    }
                                }
                            }
                        }
                    }
                    break;
                case "[object Array]":
                    break;
                case "[object ArrayBuffer]":
                    break;
                default:
                    throw new Error("MAC address content exception.MAC地址内容异常");
            }
            FinalDetectValue = true;
        } catch (e) {
            FinalDetectValue = false;
        }
        return FinalDetectValue;
    }
    function wakeMagicPacket_builder(macAddressCode) {
        let Buffer_component = require('buffer').Buffer;
        let PacketCount = 18;
        let macBit;
        let FinalMakeBuffer;
        let tempSource;
        let tempPacket;
        switch (Object.prototype.toString.call(macAddressCode)) {
            case "[object String]":
                let spSym = String(macAddressCode).substr(2, 1);
                tempSource = String(macAddressCode).split(spSym);
                break;
            case "[object Array]":
                break;
        }
        macBit = tempSource.length;
        FinalMakeBuffer = Buffer_component.alloc(macBit * PacketCount);
        tempPacket = Buffer_component.alloc(macBit);
        for (let nn = 0; nn < macBit; nn++) {
            FinalMakeBuffer[nn] = 0xff;
        }
        for (let num in tempSource) {
            tempPacket[num] = parseInt(tempSource[num], 16);
        }
        for (let initPacket = 0; initPacket < PacketCount; initPacket++) {
            tempPacket.copy(FinalMakeBuffer, (initPacket + 1) * macBit, 0, tempPacket.length);
        }
        return FinalMakeBuffer;
    }
    if (macAddressDetect(macAddress)) {
        let parameterObject = {}
        if (Object.prototype.toString.call(ConfigOption) === "[object Object]") {
            for (let item in ConfigOption) {
                switch (String(item).toLowerCase()) {
                    case "interval_time":
                        parameterObject.interval_time = ConfigOption[item];
                        break;
                    case "execute_count":
                        parameterObject.execute_count = ConfigOption[item];
                        break;
                    case "broadcast_address":
                        parameterObject.broadcast_address = ConfigOption[item];
                        break;
                    case "target_port":
                        parameterObject.target_port = ConfigOption[item];
                        break;
                    default:
                        throw new Error("");
                }
            }
        } else {
            parameterObject = {
                interval_time: 100,
                execute_count: 3,
                broadcast_address: "255.255.255.255",
                target_port: 9
            }
        }
        let wakeMagicData = wakeMagicPacket_builder(macAddress);
        let OperateSocket;
        switch (network_component.isIP(parameterObject.broadcast_address)) {
            case 4:
                OperateSocket = dgram_component.createSocket("udp4");
                break;
            case 6:
                OperateSocket = dgram_component.createSocket("udp6");
                break;
            default:
                throw new Error("");
        }
        let OperateCollect = new Promise((resolve, reject) => {
            OperateSocket.once('listening', function () {
                OperateSocket.setBroadcast(true);
            });
            let executeCount = 0;
            let dde = setInterval(() => {
                if (executeCount >= parameterObject.execute_count) {
                    OperateSocket.close();
                    clearInterval(dde);
                    resolve("wakeUp Success");
                } else {
                    OperateSocket.send(wakeMagicData, 0, wakeMagicData.length, parameterObject.target_port, parameterObject.broadcast_address, (vl) => {
                        if (vl) {
                            reject(`wakeUp Failure.${vl}`);
                        }
                    });
                    executeCount++;
                }
            }, parameterObject.interval_time);
        });
        let OperateStatus;
        let OperateMessage;
        await OperateCollect.then((value) => {
            OperateMessage = value;
            OperateStatus = true;
        }).catch((value) => {
            OperateMessage = value;
            OperateStatus = false;
        });
        if (OperateStatus) {
            return OperateMessage;
        } else {
            throw new Error(OperateMessage);
        }
    } else {
        throw new Error("MAC address content exception.MAC地址内容异常");
    }
}

module.exports = {wakeUpCurrentNetworkALLHost, wakeUpCurrentNetworkPointHost};